package com.hengpeng.common.web.tags;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.text.DecimalFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.BodyContent;

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyAccessorFactory;

import com.hengpeng.common.acl.vo.ButtonObject;
import com.hengpeng.common.web.annotation.HtmlInput;
import com.hengpeng.common.web.annotation.HtmlInputType;
import com.hengpeng.common.web.tags.vo.CommandProperty;
import com.hengpeng.common.web.tags.vo.PropertyConfig;

/**
 * <pre>
 * 由对象自动创建表单的标签
 * </pre>
 * @author linriqing
 * @version 1.0, 2006-6-16
 */
public class CommandTag extends ButtonContainerTag
{
	public static class SingleObject
	{
		String label;

		String value;
	}

	private static final long serialVersionUID = -5415000370631477211L;

	private String action;

	private int column = 1;

	private String command;

	private String exclude;

	private String method;

	private boolean needButton = true;

	private boolean needTitle = true;

	private String onblur;

	private String onchange;

	private String onSubmit;

	private List<CommandProperty> propertys;

	private boolean readonly;

	private String submitName;

	private String target;

	private String title;

	public CommandTag()
	{
		super();
		this.propertys = new ArrayList<CommandProperty>();
	}

	private String createMultipleSubmitValid(String name, PropertyConfig htmlInput)
	{
		StringBuffer check = new StringBuffer();
		check.append("isNull4");
		check.append(this.command);
		check.append("('" + htmlInput.label() + "','" + name + "','valid4");
		check.append(name);
		check.append("', 'mask4");
		check.append(name);
		check.append("');");
		return check.toString();
	}

	private String createPassworConfirmSubmitValid(String name, PropertyConfig htmlInput)
	{
		StringBuffer check = new StringBuffer();
		check.append("validResult;\r\n");
		check.append("			if($('#" + name + "').val() == $('#" + name + "copy').val())\r\n");
		check.append("			{\r\n");
		check.append("				$('#valid4" + name + "copy').hide();\r\n");
		check.append("				$('#mask4" + name + "copy').hide();\r\n");
		check.append("				validResult = true;\r\n");
		check.append("			}\r\n");
		check.append("			else\r\n");
		check.append("			{\r\n");
		check.append("				$('#valid4" + name + "copy').html(\"<label>&nbsp;</label>" + htmlInput.label() + "和"
				+ htmlInput.label() + "确认不一致\");\r\n");
		check.append("				$('#valid4" + name + "copy').show();\r\n");
		check.append("				$('#mask4" + name + "copy').show();\r\n");
		check.append("				validResult = false;\r\n");
		check.append("			}\r\n");
		return check.toString();
	}

	private String createSingleSubmitValid(String name, PropertyConfig htmlInput)
	{
		StringBuffer check = new StringBuffer();
		check.append("valid4");
		check.append(this.command);
		check.append("('" + htmlInput.label() + "','");
		if (htmlInput.pattern() != null)
		{
			check.append(htmlInput.pattern().getJspattern());
		}
		check.append("',$('#" + name + "').val(),'valid4");
		check.append(name);
		check.append("', 'mask4");
		check.append(name);
		check.append("', '");
		check.append(!htmlInput.nullable());
		check.append("');");
		return check.toString();
	}

	@Override
	public int doAfterBody() throws JspException
	{
		super.doAfterBody();
		BodyContent body = this.getBodyContent();
		body.clearBody();
		try
		{
			StringBuffer content = new StringBuffer();
			HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
			renderCommandForm(content, request, pageContext, request.getContextPath());
			getPreviousOut().print(content.toString());
		}
		catch (IOException e)
		{
			throw new JspException(e);
		}
		catch (IllegalAccessException e)
		{
			throw new JspException(e);
		}
		return SKIP_BODY;
	}

	public int doStartTag() throws JspException
	{
		super.doStartTag();
		this.propertys.clear();
		return EVAL_BODY_BUFFERED;
	}

	public String getAction()
	{
		return action;
	}

	public int getColumn()
	{
		return column;
	}

	public String getCommand()
	{
		return command;
	}

	public String getExclude()
	{
		return exclude;
	}

	public String getMethod()
	{
		return method;
	}

	public String getOnblur()
	{
		return onblur;
	}

	public String getOnchange()
	{
		return onchange;
	}

	public String getOnSubmit()
	{
		return onSubmit;
	}

	public List<CommandProperty> getPropertys()
	{
		return propertys;
	}

	public String getSubmitName()
	{
		return submitName;
	}

	public String getTab(int tabLayer)
	{
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < tabLayer; i++)
		{
			sb.append("\t");
		}
		return sb.toString();
	}

	public String getTarget()
	{
		return target;
	}

	public String getTitle()
	{
		return title;
	}

	private boolean isChecked(Object selectValue, String so, PropertyConfig htmlInput, Object inItem)
	{
		boolean isSelected = false;
		if (selectValue != null)
		{
			if (selectValue.getClass().isAssignableFrom(inItem.getClass()))
			{
				if (selectValue.getClass().isArray())
				{
					Object[] itemsArray = (Object[]) selectValue;
					for (int i = 0; i < itemsArray.length; i++)
					{
						Object item = itemsArray[i];
						String sso = wrapperElementValue(item, htmlInput);
						if (sso.equalsIgnoreCase(so))
						{
							isSelected = true;
							break;
						}
					}
				}
				else if (selectValue instanceof Collection<?>)
				{
					final Collection<?> optionCollection = (Collection<?>) selectValue;
					for (Iterator<?> it = optionCollection.iterator(); it.hasNext();)
					{
						Object item = it.next();
						String sso = wrapperElementValue(item, htmlInput);
						if (sso.equalsIgnoreCase(so))
						{
							isSelected = true;
							break;
						}
					}
				}
				else if (selectValue instanceof Map<?, ?>)
				{
					final Map<?, ?> optionMap = (Map<?, ?>) selectValue;
					for (Iterator<?> it = optionMap.entrySet().iterator(); it.hasNext();)
					{
						Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next();
						String sso = wrapperEntryValue(entry, htmlInput);
						if (sso.equalsIgnoreCase(so))
						{
							isSelected = true;
							break;
						}
					}
				}
				else
				{
					String sso = wrapperElementValue(selectValue, htmlInput);
					if (sso.equalsIgnoreCase(so))
					{
						isSelected = true;
					}
				}
			}
			else
			{
				String sso = selectValue.toString();
				if (sso.equalsIgnoreCase(so))
				{
					isSelected = true;
				}
			}
		}
		return isSelected;
	}

	private boolean isChecked(SingleObject so, PropertyConfig htmlInput, Object selectValue)
	{
		boolean isSelected = false;
		if (selectValue != null)
		{
			if (selectValue.getClass().isArray())
			{
				Object[] itemsArray = (Object[]) selectValue;
				for (int i = 0; i < itemsArray.length; i++)
				{
					Object item = itemsArray[i];
					SingleObject sso = wrapperLabelValue(item, htmlInput);
					if (sso.value.equalsIgnoreCase(so.value))
					{
						isSelected = true;
						break;
					}
				}
			}
			else if (selectValue instanceof Collection<?>)
			{
				final Collection<?> optionCollection = (Collection<?>) selectValue;
				for (Iterator<?> it = optionCollection.iterator(); it.hasNext();)
				{
					Object item = it.next();
					SingleObject sso = wrapperLabelValue(item, htmlInput);
					if (sso.value.equalsIgnoreCase(so.value))
					{
						isSelected = true;
						break;
					}
				}
			}
			else if (selectValue instanceof Map<?, ?>)
			{
				final Map<?, ?> optionMap = (Map<?, ?>) selectValue;
				for (Iterator<?> it = optionMap.entrySet().iterator(); it.hasNext();)
				{
					Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next();
					SingleObject sso = wrapperMapLabelValue(entry, htmlInput);
					if (sso.value.equalsIgnoreCase(so.value))
					{
						isSelected = true;
						break;
					}
				}
			}
			else
			{
				SingleObject sso = wrapperLabelValue(selectValue, htmlInput);
				if (sso.value.equalsIgnoreCase(so.value))
				{
					isSelected = true;
				}
			}
		}
		return isSelected;
	}

	public boolean isNeedButton()
	{
		return needButton;
	}

	public boolean isNeedTitle()
	{
		return needTitle;
	}

	public boolean isReadonly()
	{
		return readonly;
	}

	public void renderCommandForm(StringBuffer content, HttpServletRequest request, PageContext pageContext,
			String contextPath) throws JspException, IllegalAccessException
	{
		if (command != null)
		{
			Object value = request.getAttribute(command);
			List<String> submitCheck = new ArrayList<String>();
			if (value != null)
			{
				Class<?> type = value.getClass();
				List<Field> useFieldList = new ArrayList<Field>();
				List<Field> allFieldList = new ArrayList<Field>();
				// 父类的方法
				while (!type.equals(Object.class))
				{
					Field[] fields = type.getDeclaredFields();
					useFieldList.addAll(Arrays.asList(fields));
					allFieldList.addAll(Arrays.asList(fields));
					type = type.getSuperclass();
				}
				// 指定不显示的属性
				String[] excludeName = new String[0];
				if ((exclude != null) && (exclude.length() > 0))
				{
					// 属性名之间用,分隔
					excludeName = exclude.split(TagConstant.INPUT_COLLECTION_SPLIT_REGEX);
				}

				// 过滤不包括的字段
				List<Field> excludeList = new ArrayList<Field>();
				// 隐藏的字段, 分列显示的时候必须将隐藏字段放在最前面，否则无法确定什么时候该合并列
				List<Field> hiddenList = new ArrayList<Field>();
				for (Field field : useFieldList)
				{
					field.setAccessible(true);
					HtmlInput htmlInput = field.getAnnotation(HtmlInput.class);
					if (htmlInput == null)
					{
						excludeList.add(field);
					}
					else
					{
						// 找出隐藏的字段
						if (htmlInput.type().equals(HtmlInputType.HIDDEN)
								|| htmlInput.type().equals(HtmlInputType.AUTOID))
						{
							hiddenList.add(field);
						}
					}
					// 找出不包括的字段
					for (String string : excludeName)
					{
						if (field.getName().equalsIgnoreCase(string))
						{
							excludeList.add(field);
						}
					}
				}

				for (Field field : excludeList)
				{
					// 从所有属性中移除不包括的字段
					useFieldList.remove(field);
					// 从隐藏属性中移除不包括的字段
					hiddenList.remove(field);
				}

				for (Field field : hiddenList)
				{
					// 从所有属性中移除隐藏的字段
					useFieldList.remove(field);
				}

				int showPropertyCount = useFieldList.size() + this.propertys.size();

				// 字段显示顺序排序
				Comparator<Field> c = new Comparator<Field>()
				{
					@Override
					public int compare(Field o1, Field o2)
					{
						o1.setAccessible(true);
						o2.setAccessible(true);
						HtmlInput htmlInput1 = o1.getAnnotation(HtmlInput.class);
						HtmlInput htmlInput2 = o2.getAnnotation(HtmlInput.class);
						if ((htmlInput1 != null) && (htmlInput2 != null))
						{
							return htmlInput1.index() - htmlInput2.index();
						}
						else
						{
							return 0;
						}
					}
				};
				Collections.sort(useFieldList, c);

				// 重新加入隐藏的字段
				useFieldList.addAll(0, hiddenList);

				if (!readonly)
				{
					content.append("\r\n<script type=\"text/javascript\">\r\n ");
					content.append("	function valid4" + command
							+ "(label, pattern, value, validEle, maskEle, isCheckNull){\r\n");
					content.append("		value = value.replace(/(^\\s*)|(\\s*$)/g, \"\");\r\n");
					content.append("		if(value.length > 0)\r\n");
					content.append("		{\r\n");
					content.append("			if(new RegExp(pattern).test(value))\r\n");
					content.append("			{\r\n");
					content.append("				$('#'+validEle+'').hide();\r\n");
					content.append("				$('#'+maskEle+'').hide();\r\n");
					content.append("				return true;\r\n");
					content.append("			}\r\n");
					content.append("			else\r\n");
					content.append("			{\r\n");
					content.append("				$('#'+validEle+'').html(\"<label>&nbsp;</label>\"+label+\"格式错误\");\r\n");
					content.append("				$('#'+validEle+'').show();\r\n");
					content.append("				$('#'+maskEle+'').show();\r\n");
					content.append("				return false;\r\n");
					content.append("			};\r\n");
					content.append("		}\r\n");
					content.append("		else\r\n");
					content.append("		{\r\n");
					content.append("			if(isCheckNull == 'true')\r\n");
					content.append("			{\r\n");
					content.append("				$('#'+validEle+'').html(\"<label>&nbsp;</label>\"+label+\"不能为空\");\r\n");
					content.append("				$('#'+validEle+'').show();\r\n");
					content.append("				$('#'+maskEle+'').show();\r\n");
					content.append("				return false;\r\n");
					content.append("			}\r\n");
					content.append("			else\r\n");
					content.append("			{\r\n");
					content.append("				$('#'+validEle+'').hide();\r\n");
					content.append("				$('#'+maskEle+'').hide();\r\n");
					content.append("				return true;\r\n");
					content.append("			}\r\n");
					content.append("		}\r\n");
					content.append("	}\r\n");
					content.append("	function isNull4" + command + "(label, eleName, validEle, maskEle){\r\n");
					content.append("		var flag=false;\r\n");
					content.append("		var checkvalue = $(\"input[name='\"+eleName+\"']\");\r\n");
					content.append("		checkvalue.each(function()\r\n");
					content.append("		{\r\n");
					content.append("			if(this.checked==true)\r\n");
					content.append("			{\r\n");
					content.append("				flag = true;\r\n");
					content.append("			}\r\n");
					content.append("		});\r\n");
					content.append("		if(!flag)\r\n");
					content.append("		{\r\n");
					content.append("			$('#'+validEle+'').html(\"<label>&nbsp;</label>\"+label+\"不能为空\");\r\n");
					content.append("			$('#'+validEle+'').show();\r\n");
					content.append("			$('#'+maskEle+'').show();\r\n");
					content.append("			return false;\r\n");
					content.append("		}\r\n");
					content.append("		else\r\n");
					content.append("		{\r\n");
					content.append("			$('#'+validEle+'').hide();\r\n");
					content.append("			$('#'+maskEle+'').hide();\r\n");
					content.append("			return true;\r\n");
					content.append("		}\r\n");
					content.append("	}\r\n");
					// 链接和按钮提交js脚本
					if (this.needButton)
					{
						content.append("// " + command + "数据列表表单提交脚本\r\n");
						content.append("function _submitAction4" + command + "(obj, action, params)\r\n");
						content.append("{\r\n");
						content.append("		var submitForm;\r\n");
						content.append("		while ((obj.parentNode) && (obj.parentNode.tagName) && (!obj.parentNode.tagName.match(/FORM/i)))\r\n");
						content.append("		{\r\n");
						content.append("			obj = obj.parentNode;\r\n");
						content.append("		}\r\n");
						content.append("		submitForm = obj.parentNode;\r\n");
						content.append("		if(!submitForm)\r\n");
						content.append("		{\r\n");
						content.append("			submitForm = document.createElement(\"form\");\r\n");
						content.append("			document.body.appendChild(submitForm);\r\n");
						content.append("		}\r\n");
						content.append("		submitForm.setAttribute(\"action\", action);\r\n");
						content.append("		submitForm.setAttribute(\"method\", \"POST\");\r\n");
						content.append("		for(var key in params)\r\n");
						content.append("		{\r\n");
						content.append("				var hiddenField = document.createElement(\"input\");\r\n");
						content.append("				hiddenField.setAttribute(\"type\", \"hidden\");\r\n");
						content.append("				hiddenField.setAttribute(\"name\", key);\r\n");
						content.append("				hiddenField.setAttribute(\"value\", params[key]);\r\n");
						content.append("				submitForm.appendChild(hiddenField);\r\n");
						content.append("		}\r\n");
						content.append("if(submit4" + this.command + "()) submitForm.submit();\r\n");
						content.append("}\r\n");
					}
					content.append("</script>\r\n");

					content.append("<form id=\"" + command + "\" ");
					if (this.action != null)
					{
						String extractAction = this.action;
						if (this.action.startsWith("/"))
						{
							extractAction = request.getContextPath() + this.action;
						}
						content.append(" action=\"" + evaluate(extractAction, String.class, pageContext) + "\"");
					}
					if (this.method != null)
					{
						content.append(" method=\"" + this.method + "\"");
					}
					else
					{
						content.append(" method=\"post\"");
					}
					if (this.target != null)
					{
						content.append(" target=\"" + this.target + "\"");
					}
					if (this.needButton)
					{
						content.append(" onSubmit=\"return submit4" + this.command + "();\"");
					}
					content.append(">");
				}
				if (needTitle)
				{
					content.append("\r\n<table class=\"data_table_main\">\r\n");
					content.append("<tr>\r\n<td background=\"" + contextPath + "/layout/list/tab_top.gif\">\r\n");
					content.append("<!-- " + command + "标题头 -->\r\n");
					content.append("<table class=\"data_table_title\">\r\n");
					renderTitle(content, contextPath);
					content.append("</table>\r\n</td>\r\n</tr>\r\n<tr>\r\n<td>\r\n");
					content.append("\r\n<table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\r\n<tr>\r\n<td width=\"8\" background=\""
							+ contextPath + "/layout/list/tab_left.gif\">&nbsp;</td>\r\n<td>\r\n");
				}
				content.append("\r\n<!-- " + command + "数据区 -->\r\n");
				content.append("<table id=\"main_table4" + command + "\" class=\"data_table_command\">\r\n");

				StringBuffer hiddenContent = new StringBuffer();
				int fieldIndex = 0;
				int showFieldIndex = 0;
				for (Field field : useFieldList)
				{
					for (CommandProperty customProperty : propertys)
					{
						if ((customProperty.getIndex() >= 0) && (customProperty.getIndex() == fieldIndex))
						{
							if (customProperty.getContent() != null)
							{
								showFieldIndex++;
								if (this.column > 1)
								{
									if (showFieldIndex % this.column == 1)
									{
										content.append("<tr>\r\n<td class=\"data_tab_tdr\">");
										content.append(customProperty.getLabel());
										if ((customProperty.getTips() != null)
												&& (customProperty.getTips().length() > 0))
										{
											content.append("<span id=\"inputTips\" style=\"z-index: "
													+ (2000 - fieldIndex)
													+ ";\" >(<a href=\"javascript:void(0)\" >?<span class=\"tipsdetail\"><span class='cbl'>"
													+ customProperty.getTips()
													+ "</span></span></a>)</span>&nbsp;&nbsp;&nbsp;&nbsp;");
										}
										content.append("</td>\r\n<td class=\"data_tab_tdl\">");
									}
									else
									{
										content.append("</td>\r\n<td class=\"data_tab_tdr\" >");
										content.append(customProperty.getLabel());
										if ((customProperty.getTips() != null)
												&& (customProperty.getTips().length() > 0))
										{
											content.append("<span id=\"inputTips\" style=\"z-index: "
													+ (2000 - fieldIndex)
													+ ";\" >(<a href=\"javascript:void(0)\" >?<span class=\"tipsdetail\"><span class='cbl'>"
													+ customProperty.getTips()
													+ "</span></span></a>)</span>&nbsp;&nbsp;&nbsp;&nbsp;");
										}
										content.append("</td>\r\n<td class=\"data_tab_tdl\">");
									}
								}
								else
								{
									content.append("<tr>\r\n<td class=\"data_tab_tdr\">");
									content.append(customProperty.getLabel());
									if ((customProperty.getTips() != null) && (customProperty.getTips().length() > 0))
									{
										content.append("<span id=\"inputTips\" style=\"z-index: "
												+ (2000 - fieldIndex)
												+ ";\" >(<a href=\"javascript:void(0)\" >?<span class=\"tipsdetail\"><span class='cbl'>"
												+ customProperty.getTips()
												+ "</span></span></a>)</span>&nbsp;&nbsp;&nbsp;&nbsp;");
									}
									content.append("</td>\r\n<td class=\"data_tab_tdl\">");
								}

								content.append(customProperty.getContent());

								if (this.column > 1)
								{
									if (showFieldIndex == showPropertyCount)
									{
										if ((showFieldIndex % this.column) == 0)
										{
											content.append("</td>\r\n</tr>\r\n");
										}
										else
										{
											int remainColumn = this.column - (showFieldIndex % this.column);
											content.append("</td>\r\n<td colspan=\"" + (remainColumn * 2)
													+ "\" class=\"data_tab_tdl\">&nbsp;</td></tr>\r\n");
										}
									}
									else
									{
										if ((showFieldIndex % this.column) == 0)
										{
											content.append("</td>\r\n</tr>\r\n");
										}
									}
								}
								else
								{
									content.append("</td>\r\n</tr>\r\n");
								}
							}
						}
					}

					fieldIndex++;
					field.setAccessible(true);
					HtmlInput htmlInputAnnotation = field.getAnnotation(HtmlInput.class);
					PropertyConfig htmlInput = new PropertyConfig(htmlInputAnnotation);
					if (htmlInput != null)
					{
						if (!htmlInput.type().equals(HtmlInputType.HIDDEN)
								&& !htmlInput.type().equals(HtmlInputType.AUTOID))
						{
							showFieldIndex++;
							if (this.column > 1)
							{
								if (showFieldIndex % this.column == 1)
								{
									content.append("<tr>\r\n<td class=\"data_tab_tdr\">");
									content.append(htmlInput.label());
									if (htmlInput.tips().length() > 0)
									{
										content.append("<span id=\"inputTips\" style=\"z-index: "
												+ (2000 - fieldIndex)
												+ ";\" >(<a href=\"javascript:void(0)\" >?<span class=\"tipsdetail\"><span class='cbl'>"
												+ htmlInput.tips()
												+ "</span></span></a>)</span>&nbsp;&nbsp;&nbsp;&nbsp;");
									}
									content.append("</td>\r\n<td class=\"data_tab_tdl\">");
								}
								else
								{
									content.append("</td>\r\n<td class=\"data_tab_tdr\">");
									content.append(htmlInput.label());
									if (htmlInput.tips().length() > 0)
									{
										content.append("<span id=\"inputTips\" style=\"z-index: "
												+ (2000 - fieldIndex)
												+ ";\" >(<a href=\"javascript:void(0)\" >?<span class=\"tipsdetail\"><span class='cbl'>"
												+ htmlInput.tips()
												+ "</span></span></a>)</span>&nbsp;&nbsp;&nbsp;&nbsp;");
									}
									content.append("</td>\r\n<td class=\"data_tab_tdl\">");
								}
							}
							else
							{
								content.append("<tr>\r\n<td class=\"data_tab_tdr\">");
								content.append(htmlInput.label());
								if (htmlInput.tips().length() > 0)
								{
									content.append("<span id=\"inputTips\" style=\"z-index: "
											+ (2000 - fieldIndex)
											+ ";\" >(<a href=\"javascript:void(0)\" >?<span class=\"tipsdetail\"><span class='cbl'>"
											+ htmlInput.tips() + "</span></span></a>)</span>&nbsp;&nbsp;&nbsp;&nbsp;");
								}
								content.append("</td>\r\n<td class=\"data_tab_tdl\">");
							}
						}
						String itemsName = htmlInput.items();
						String inputId = field.getName();
						Object fromRequest = null;
						if (htmlInput.inputId().length() > 0)
						{
							inputId = htmlInput.inputId();
							fromRequest = request.getAttribute(inputId);
						}
						if (!readonly)
						{
							switch (htmlInput.type())
							{
								case CHECKBOX:
									submitCheck.add(createMultipleSubmitValid(inputId, htmlInput));
									content.append(renderInput4Multiple(value, field, htmlInput, "checkbox",
											submitCheck, inputId, request, itemsName, fromRequest));
									break;
								case HIDDEN:
									hiddenContent.append(renderInput4Simply(value, field, htmlInput, "hidden",
											submitCheck, contextPath, inputId, fromRequest));
									hiddenContent.append("\r\n");
									break;
								case AUTOID:
									hiddenContent.append(renderInput4Simply(value, field, htmlInput, "hidden",
											submitCheck, contextPath, inputId, fromRequest));
									hiddenContent.append("\r\n");
									break;
								case ID:
									submitCheck.add(createSingleSubmitValid(inputId, htmlInput));
									content.append(renderInput4Simply(value, field, htmlInput, "text", submitCheck,
											contextPath, inputId, fromRequest));
									hiddenContent.append(renderInput4Simply(value, field, htmlInput, "hidden",
											submitCheck, contextPath, inputId, fromRequest));
									hiddenContent.append("\r\n");
									break;
								case LABEL:
									content.append(wrapperSimplyValue(value, field, htmlInput, fromRequest));
									break;
								case PASSWORD:
									submitCheck.add(createSingleSubmitValid(inputId, htmlInput));
									content.append(renderInput4Simply(value, field, htmlInput, "password", submitCheck,
											contextPath, inputId, fromRequest));
									break;
								case PASSWORD_REPEAT:
									submitCheck.add(createSingleSubmitValid(inputId, htmlInput));
									content.append(renderInput4Simply(value, field, htmlInput, "password", submitCheck,
											contextPath, inputId, fromRequest));
									content.append("<br />");
									submitCheck.add(createSingleSubmitValid(inputId + "copy", htmlInput));
									content.append(renderInput4PwdConfirm(value, field, htmlInput, "password",
											submitCheck, contextPath, inputId, fromRequest));
									submitCheck.add(createPassworConfirmSubmitValid(inputId, htmlInput));
									break;
								case RADIOBOX:
									submitCheck.add(createMultipleSubmitValid(inputId, htmlInput));
									content.append(renderInput4Multiple(value, field, htmlInput, "radio", submitCheck,
											inputId, request, itemsName, fromRequest));
									break;
								case TEXT:
									submitCheck.add(createSingleSubmitValid(inputId, htmlInput));
									content.append(renderInput4Simply(value, field, htmlInput, "text", submitCheck,
											contextPath, inputId, fromRequest));
									break;
								case TEXTAREA:
									submitCheck.add(createSingleSubmitValid(inputId, htmlInput));
									content.append(renderInput4TextArea(value, field, htmlInput, "textarea",
											submitCheck, contextPath, inputId, fromRequest));
									break;
								case SELECT:
									submitCheck.add(createSingleSubmitValid(inputId, htmlInput));
									content.append(renderInput4Select(value, field, htmlInput, submitCheck, inputId,
											request, itemsName, fromRequest));
									break;
								default:
									submitCheck.add(createSingleSubmitValid(inputId, htmlInput));
									content.append(renderInput4Simply(value, field, htmlInput, "text", submitCheck,
											contextPath, inputId, fromRequest));
									break;
							}
						}
						else
						{
							switch (htmlInput.type())
							{
								case CHECKBOX:
								case RADIOBOX:
								case SELECT:
									Object attribute = null;
									if ((itemsName != null) && (itemsName.length() > 0))
									{
										attribute = request.getAttribute(itemsName);
									}
									content.append(wrapperMultipleValue(field, value, htmlInput, attribute));
									break;
								case LABEL:
								case TEXTAREA:
								case PASSWORD:
								case TEXT:
								case ID:
									content.append(wrapperSimplyValue(value, field, htmlInput, fromRequest));
									break;
								case HIDDEN:
								case AUTOID:
									break;
								default:
									content.append(wrapperSimplyValue(value, field, htmlInput, fromRequest));
									break;
							}
						}
						if (!htmlInput.type().equals(HtmlInputType.HIDDEN)
								&& !htmlInput.type().equals(HtmlInputType.AUTOID))
						{
							if (this.column > 1)
							{
								if (showFieldIndex == showPropertyCount)
								{
									if ((showFieldIndex % this.column) == 0)
									{
										content.append("</td>\r\n</tr>\r\n");
									}
									else
									{
										int remainColumn = this.column - (showFieldIndex % this.column);
										content.append("</td>\r\n<td colspan=\"" + (remainColumn * 2)
												+ "\" class=\"data_tab_tdl\">&nbsp;</td></tr>\r\n");
									}
								}
								else
								{
									if ((showFieldIndex % this.column) == 0)
									{
										content.append("</td>\r\n</tr>\r\n");
									}
									else
									{
										continue;
									}
								}
							}
							else
							{
								content.append("</td>\r\n</tr>\r\n");
							}
						}
					}
				}

				// 输出Index设置很大的
				for (CommandProperty customProperty : propertys)
				{
					if (customProperty.getIndex() >= fieldIndex)
					{
						if (customProperty.getContent() != null)
						{
							showFieldIndex++;
							if (this.column > 1)
							{
								if (showFieldIndex % this.column == 1)
								{
									content.append("<tr>\r\n<td class=\"data_tab_tdr\">");
									content.append(customProperty.getLabel());
									if ((customProperty.getTips() != null) && (customProperty.getTips().length() > 0))
									{
										content.append("<span id=\"inputTips\" style=\"z-index: "
												+ (2000 - fieldIndex)
												+ ";\" >(<a href=\"javascript:void(0)\" >?<span class=\"tipsdetail\"><span class='cbl'>"
												+ customProperty.getTips()
												+ "</span></span></a>)</span>&nbsp;&nbsp;&nbsp;&nbsp;");
									}
									content.append("</td>\r\n<td class=\"data_tab_tdl\">");
								}
								else
								{
									content.append("</td>\r\n<td class=\"data_tab_tdr\">");
									content.append(customProperty.getLabel());
									if ((customProperty.getTips() != null) && (customProperty.getTips().length() > 0))
									{
										content.append("<span id=\"inputTips\" style=\"z-index: "
												+ (2000 - fieldIndex)
												+ ";\" >(<a href=\"javascript:void(0)\" >?<span class=\"tipsdetail\"><span class='cbl'>"
												+ customProperty.getTips()
												+ "</span></span></a>)</span>&nbsp;&nbsp;&nbsp;&nbsp;");
									}
									content.append("</td>\r\n<td class=\"data_tab_tdl\">");
								}
							}
							else
							{
								content.append("<tr>\r\n<td class=\"data_tab_tdr\" >");
								content.append(customProperty.getLabel());
								if ((customProperty.getTips() != null) && (customProperty.getTips().length() > 0))
								{
									content.append("<span id=\"inputTips\" style=\"z-index: "
											+ (2000 - fieldIndex)
											+ ";\" >(<a href=\"javascript:void(0)\" >?<span class=\"tipsdetail\"><span class='cbl'>"
											+ customProperty.getTips()
											+ "</span></span></a>)</span>&nbsp;&nbsp;&nbsp;&nbsp;");
								}
								content.append("</td>\r\n<td class=\"data_tab_tdl\">");
							}

							content.append(customProperty.getContent());

							if (this.column > 1)
							{
								if (showFieldIndex == showPropertyCount)
								{
									if ((showFieldIndex % this.column) == 0)
									{
										content.append("</td>\r\n</tr>\r\n");
									}
									else
									{
										int remainColumn = this.column - (showFieldIndex % this.column);
										content.append("</td>\r\n<td colspan=\"" + (remainColumn * 2)
												+ "\" class=\"data_tab_tdl\">&nbsp;</td></tr>\r\n");
									}
								}
								else
								{
									if ((showFieldIndex % this.column) == 0)
									{
										content.append("</td>\r\n</tr>\r\n");
									}
								}
							}
							else
							{
								content.append("</td>\r\n</tr>\r\n");
							}
						}
					}
				}
				// 输出默认位置的
				for (CommandProperty customProperty : propertys)
				{
					if (customProperty.getIndex() == -1)
					{
						if (customProperty.getContent() != null)
						{
							showFieldIndex++;
							if (this.column > 1)
							{
								if (showFieldIndex % this.column == 1)
								{
									content.append("<tr>\r\n<td class=\"data_tab_tdr\">");
									content.append(customProperty.getLabel());
									if ((customProperty.getTips() != null) && (customProperty.getTips().length() > 0))
									{
										content.append("<span id=\"inputTips\" style=\"z-index: "
												+ (2000 - fieldIndex)
												+ ";\" >(<a href=\"javascript:void(0)\" >?<span class=\"tipsdetail\"><span class='cbl'>"
												+ customProperty.getTips()
												+ "</span></span></a>)</span>&nbsp;&nbsp;&nbsp;&nbsp;");
									}
									content.append("</td>\r\n<td class=\"data_tab_tdl\">");
								}
								else
								{
									content.append("</td>\r\n<td class=\"data_tab_tdr\" >");
									content.append(customProperty.getLabel());
									if ((customProperty.getTips() != null) && (customProperty.getTips().length() > 0))
									{
										content.append("<span id=\"inputTips\" style=\"z-index: "
												+ (2000 - fieldIndex)
												+ ";\" >(<a href=\"javascript:void(0)\" >?<span class=\"tipsdetail\"><span class='cbl'>"
												+ customProperty.getTips()
												+ "</span></span></a>)</span>&nbsp;&nbsp;&nbsp;&nbsp;");
									}
									content.append("</td>\r\n<td class=\"data_tab_tdl\">");
								}
							}
							else
							{
								content.append("<tr>\r\n<td class=\"data_tab_tdr\">");
								content.append(customProperty.getLabel());
								if ((customProperty.getTips() != null) && (customProperty.getTips().length() > 0))
								{
									content.append("<span id=\"inputTips\" style=\"z-index: "
											+ (2000 - fieldIndex)
											+ ";\" >(<a href=\"javascript:void(0)\" >?<span class=\"tipsdetail\"><span class='cbl'>"
											+ customProperty.getTips()
											+ "</span></span></a>)</span>&nbsp;&nbsp;&nbsp;&nbsp;");
								}
								content.append("</td>\r\n<td class=\"data_tab_tdl\">");
							}

							content.append(customProperty.getContent());

							if (this.column > 1)
							{
								if (showFieldIndex == showPropertyCount)
								{
									if ((showFieldIndex % this.column) == 0)
									{
										content.append("</td>\r\n</tr>\r\n");
									}
									else
									{
										int remainColumn = this.column - (showFieldIndex % this.column);
										content.append("</td>\r\n<td colspan=\"" + (remainColumn * 2)
												+ "\" class=\"data_tab_tdl\">&nbsp;</td></tr>\r\n");
									}
								}
								else
								{
									if ((showFieldIndex % this.column) == 0)
									{
										content.append("</td>\r\n</tr>\r\n");
									}
								}
							}
							else
							{
								content.append("</td>\r\n</tr>\r\n");
							}
						}
					}
				}

				if (needButton)
				{
					content.append("<tr>\r\n<td colspan=\"" + this.column * 2
							+ "\" align=\"center\" height=\"25\" class=\"data_tab_td\">");
					List<ButtonObject> buttons = this.getButtons();
					for (ButtonObject buttonTag : buttons)
					{
						String extractAction = buttonTag.getDestination();
						if (buttonTag.getDestination().startsWith("/"))
						{
							extractAction = request.getContextPath() + extractAction;
						}
						extractAction = (String) evaluate(extractAction, String.class, pageContext);

						String customEvent = "true";
						if ((buttonTag.getEvent() != null) && (buttonTag.getEvent().length() > 0))
						{
							customEvent = (String) evaluate(buttonTag.getEvent(), String.class, pageContext);
						}
						if (buttonTag.getImage() != null)
						{
							content.append("<img src=\"" + contextPath + buttonTag.getImage()
									+ "\" width=\"16\" height=\"16\" />");
						}
						content.append("<button type=\"button\" onclick=\"javascript:if(" + customEvent
								+ "){void(_submitAction4" + command + "(this,'" + getUrlByLink(extractAction) + "',"
								+ getUrlParamByLink(extractAction) + "));return false;}\" ");
						if (buttonTag.getDescription() != null)
						{
							content.append(" title=\"" + buttonTag.getDescription() + "\" ");
						}
						content.append(" />·" + buttonTag.getShowText() + "·</button>" + "&nbsp;&nbsp;");
					}
					content.append("<button type=\"button\" onclick=\"javascript:void(history.back(-1))\" >·返回·</button>");
					content.append("</td>\r\n</tr>\r\n");
				}
				content.append("</table>\r\n");
				if (needTitle)
				{
					content.append("</td>\r\n<td width=\"8\" background=\"" + contextPath
							+ "/layout/list/tab_right.gif\">&nbsp;</td> </tr>\r\n</table>");
					content.append("\r\n</td>\r\n</tr>\r\n<tr>\r\n<td background=\"" + contextPath
							+ "/layout/list/tab_bottom.gif\">\r\n");
					content.append("<table class=\"data_table_pagination\" align='center' cellpadding='0' cellspacing='0'>\r\n");
					content.append("<tr><td width=\"12\" height=\"35\"><img src=\"" + contextPath
							+ "/layout/list/tab_left_bottom.gif\" width=\"12\" height=\"35\" /></td>");
					content.append("<td>&nbsp;</td><td width=\"16\"><img src=\"" + contextPath
							+ "/layout/list/tab_right_bottom.gif\" width=\"16\" height=\"35\" /></td></tr></table>\r\n");
					content.append("</td>\r\n</tr>\r\n</table>\r\n");
				}
				content.append("<!-- " + command + "结束 -->\r\n");
				content.append(hiddenContent);
				content.append("</form>\r\n");
				if (!readonly)
				{
					content.append("<script type=\"text/javascript\">\r\n ");
					content.append("	function submit4" + command + "(){\r\n");
					content.append("		var validResult = true;\r\n");
					if (this.onSubmit != null)
					{
						content.append("		if(validResult){\r\n");
						content.append("			validResult = " + this.onSubmit + ";\r\n");
						content.append("		}\r\n");
					}
					for (String string : submitCheck)
					{
						content.append("		if(validResult){\r\n");
						content.append("			validResult = " + string + "\r\n");
						content.append("		}\r\n");
					}
					content.append("		return validResult;\r\n");
					content.append("	}\r\n");
					content.append("	new ResizeWidget('main_table4" + command + "');\r\n");
					content.append("</script>\r\n");
				}
			}
		}
	}

	private String renderElement(Object selectValue, String so, PropertyConfig htmlInput, Object item)
			throws JspException
	{
		StringBuffer string = new StringBuffer();
		if (isChecked(selectValue, so, htmlInput, item))
		{
			string.append(wrapperElementShowValue(item, htmlInput)).append(TagConstant.INPUT_COLLECTION_SPLIT_REGEX);
		}
		return string.toString();
	}

	protected StringBuffer renderInput4Multiple(Object value, Field field, PropertyConfig htmlInput, String type,
			List<String> submit, String inputId, HttpServletRequest req, String itemsName, Object fromRequest)
			throws JspException, IllegalArgumentException, IllegalAccessException
	{
		StringBuffer sb = new StringBuffer();
		if (itemsName != null)
		{
			Object selected = fromRequest;
			if (selected == null)
			{
				if (value != null)
				{
					selected = field.get(value);
				}
			}
			Object itemsObject = null;
			if (itemsName.length() > 0)
			{
				itemsObject = req.getAttribute(itemsName);
			}
			Class<?> boundType = field.getType();
			if (itemsObject == null && boundType != null && boundType.isEnum())
			{
				itemsObject = boundType.getEnumConstants();
			}
			if (boundType != null)
			{
				if (boundType.isArray())
				{
					Class<?> componentType = boundType.getComponentType();
					if (itemsObject == null && componentType != null && componentType.isEnum())
					{
						itemsObject = componentType.getEnumConstants();
					}
				}
				else if (Collection.class.isAssignableFrom(boundType))
				{
					Type genericType = field.getGenericType();
					Class<?> componentType = (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[0];
					if (itemsObject == null && componentType != null && componentType.isEnum())
					{
						itemsObject = componentType.getEnumConstants();
					}
				}
				else if (Map.class.isAssignableFrom(boundType))
				{
					Type genericType = field.getGenericType();
					Class<?> componentType = (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[1];
					if (itemsObject == null && componentType != null && componentType.isEnum())
					{
						itemsObject = componentType.getEnumConstants();
					}
				}
			}
			if (itemsObject != null)
			{
				if (itemsObject.getClass().isArray())
				{
					Object[] itemsArray = (Object[]) itemsObject;
					for (int i = 0; i < itemsArray.length; i++)
					{
						Object item = itemsArray[i];
						SingleObject so = wrapperLabelValue(item, htmlInput);
						sb.append(renderInputMultuple(inputId, type, selected, so, htmlInput));
					}
				}
				else if (itemsObject instanceof Collection<?>)
				{
					final Collection<?> optionCollection = (Collection<?>) itemsObject;
					for (Iterator<?> it = optionCollection.iterator(); it.hasNext();)
					{
						Object item = it.next();
						SingleObject so = wrapperLabelValue(item, htmlInput);
						sb.append(renderInputMultuple(inputId, type, selected, so, htmlInput));
					}
				}
				else if (itemsObject instanceof Map<?, ?>)
				{
					final Map<?, ?> optionMap = (Map<?, ?>) itemsObject;
					for (Iterator<?> it = optionMap.entrySet().iterator(); it.hasNext();)
					{
						Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next();
						SingleObject so = wrapperMapLabelValue(entry, htmlInput);
						sb.append(renderInputMultuple(inputId, type, selected, so, htmlInput));
					}
				}
				else
				{
					throw new IllegalArgumentException("Attribute 'items' must be a Collection, an Array or a Map");
				}
			}
		}
		if (!htmlInput.nullable())
		{
			sb.append("<span style=\"color:red;\">*</span>");
		}
		sb.append("<span style=\"color:gray;font-style: italic;font-size: small;\">" + htmlInput.pattern().getHint()
				+ "</span>\r\n<div id=\"mask4" + inputId + "\" style=\"display: none;\"></div>\r\n<div id=\"valid4"
				+ inputId + "\" style=\"display: none;color: red;font-size: small;\"></div>\r\n");
		return sb;
	}

	protected String renderInput4PwdConfirm(Object value, Field field, PropertyConfig htmlInput, String type,
			List<String> submit, String contextPath, String name, Object fromRequest) throws IllegalAccessException
	{
		String onblurExt = "";
		if (this.onblur != null)
		{
			onblurExt = this.onblur;
		}
		String onchangeExt = "";
		if (this.onchange != null)
		{
			onchangeExt = this.onchange;
		}
		onblurExt = onblurExt.replaceAll("javascript:", "");
		onchangeExt = onchangeExt.replaceAll("javascript:", "");

		StringBuffer string = new StringBuffer();
		Object renderValue = fromRequest;
		if (renderValue == null)
		{
			if (value != null)
			{
				renderValue = field.get(value);
			}
		}

		name = name + "copy";
		String showValue = "";
		Class<?> fieldType = field.getType();
		if (renderValue != null)
		{
			String pattern = htmlInput.format();
			if ((pattern != null) && pattern.length() > 0)
			{
				if (Date.class.isAssignableFrom(fieldType))
				{
					SimpleDateFormat sdf = new SimpleDateFormat(pattern);
					showValue = sdf.format((Date) renderValue);
				}
				else if (Integer.class.isAssignableFrom(fieldType))
				{
					DecimalFormat df = new DecimalFormat(pattern);
					showValue = df.format(renderValue);
				}
				else
				{
					MessageFormat mf = new MessageFormat(pattern);
					showValue = mf.format(renderValue);
				}
			}
			else
			{
				showValue = renderValue.toString();
			}
		}
		string.append("<input id=\"" + name + "\" type=\"" + type + "\" name=\"" + name + "\" value=\"" + showValue
				+ "\" ");
		if (!htmlInput.pattern().equals(com.hengpeng.common.web.annotation.HtmlInputPattern.NORMAL))
		{
			string.append("onchange=\"javascript: valid4" + this.command + "('" + htmlInput.label() + "','"
					+ htmlInput.pattern().getJspattern() + "',this.value,'valid4" + name + "', 'mask4" + name + "', '"
					+ !htmlInput.nullable() + "');" + onchangeExt + "\" ");
			string.append("onblur=\"javascript: valid4" + this.command + "('" + htmlInput.label() + "','"
					+ htmlInput.pattern().getJspattern() + "',this.value,'valid4" + name + "', 'mask4" + name + "', '"
					+ !htmlInput.nullable() + "');" + onblurExt + "\" ");
			string.append("/>");
			if (!"hidden".equalsIgnoreCase(type))
			{
				string.append("&nbsp;");
			}
			if (!htmlInput.nullable())
			{
				string.append("<span style=\"color:red;\">*</span>");
				string.append("<span style=\"color:gray;font-style: italic;font-size: small;\">" + "请确认"
						+ htmlInput.label() + "</span>");
			}
		}
		else
		{
			string.append("/>");
			if (!"hidden".equalsIgnoreCase(type))
			{
				string.append("&nbsp;");
			}
			if (!htmlInput.nullable())
			{
				string.append("<span style=\"color:red;\">*</span>");
				string.append("<span style=\"color:gray;font-style: italic;font-size: small;\">" + "请确认"
						+ htmlInput.label() + "</span>");
			}
		}
		if (!"hidden".equalsIgnoreCase(type))
		{
			string.append("\r\n<div id=\"mask4" + name + "\" style=\"display: none;\"></div>\r\n<div id=\"valid4"
					+ name + "\" style=\"display: none;color: red;font-size: small;\"></div>\r\n");
		}
		return string.toString();
	}

	protected StringBuffer renderInput4Select(Object value, Field field, PropertyConfig htmlInput, List<String> submit,
			String name, HttpServletRequest req, String itemsName, Object fromRequest) throws JspException,
			IllegalArgumentException, IllegalAccessException
	{
		String onblurchange = "";
		if (this.onblur != null)
		{
			onblurchange = "onblur=\"" + this.onblur + "\" ";
		}
		if (this.onchange != null)
		{
			onblurchange = onblurchange + "onchange=\"" + this.onchange + "\" ";
		}
		StringBuffer sb = new StringBuffer();
		if (itemsName != null)
		{
			Object selected = fromRequest;
			if (selected == null)
			{
				if (value != null)
				{
					selected = field.get(value);
				}
			}
			Object itemsObject = null;
			if (itemsName.length() > 0)
			{
				itemsObject = req.getAttribute(itemsName);
			}
			Class<?> boundType = field.getType();
			if (itemsObject == null && boundType != null && boundType.isEnum())
			{
				itemsObject = boundType.getEnumConstants();
			}
			String multiple = "multiple";
			if (boundType != null)
			{
				if (boundType.isArray())
				{
					Class<?> componentType = boundType.getComponentType();
					if (itemsObject == null && componentType != null && componentType.isEnum())
					{
						itemsObject = componentType.getEnumConstants();
					}
				}
				else if (Collection.class.isAssignableFrom(boundType))
				{
					Type genericType = field.getGenericType();
					Class<?> componentType = (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[0];
					if (itemsObject == null && componentType != null && componentType.isEnum())
					{
						itemsObject = componentType.getEnumConstants();
					}
				}
				else if (Map.class.isAssignableFrom(boundType))
				{
					Type genericType = field.getGenericType();
					Class<?> componentType = (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[1];
					if (itemsObject == null && componentType != null && componentType.isEnum())
					{
						itemsObject = componentType.getEnumConstants();
					}
				}
				else
				{
					multiple = "";
				}
			}
			sb.append("<select id=\"" + name + "\" name=\"" + name + "\" " + onblurchange + " " + multiple + ">\r\n");
			if (htmlInput.nullable())
			{
				sb.append("<option value=''>--请选择--</option>\r\n");
			}
			if (itemsObject != null)
			{
				if (itemsObject.getClass().isArray())
				{
					Object[] itemsArray = (Object[]) itemsObject;
					for (int i = 0; i < itemsArray.length; i++)
					{
						Object item = itemsArray[i];
						SingleObject so = wrapperLabelValue(item, htmlInput);
						sb.append(renderInputOption(selected, so, htmlInput, selected));
					}
				}
				else if (itemsObject instanceof Collection<?>)
				{
					final Collection<?> optionCollection = (Collection<?>) itemsObject;
					for (Iterator<?> it = optionCollection.iterator(); it.hasNext();)
					{
						Object item = it.next();
						SingleObject so = wrapperLabelValue(item, htmlInput);
						sb.append(renderInputOption(selected, so, htmlInput, selected));
					}
				}
				else if (itemsObject instanceof Map<?, ?>)
				{
					final Map<?, ?> optionMap = (Map<?, ?>) itemsObject;
					for (Iterator<?> it = optionMap.entrySet().iterator(); it.hasNext();)
					{
						Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next();
						SingleObject so = wrapperMapLabelValue(entry, htmlInput);
						sb.append(renderInputOption(selected, so, htmlInput, selected));
					}
				}
				else
				{
					throw new IllegalArgumentException("Attribute 'items' must be a Collection, an Array or a Map");
				}
			}
		}
		sb.append("</select>");
		if (!htmlInput.nullable())
		{
			sb.append("<span style=\"color:red;\">*</span>");
		}
		sb.append("<span style=\"color:gray;font-style: italic;font-size: small;\">" + htmlInput.pattern().getHint()
				+ "</span>\r\n<div id=\"mask4" + name + "\" style=\"display: none;\"></div>\r\n<div id=\"valid4" + name
				+ "\" style=\"display: none;color: red;font-size: small;\"></div>\r\n");
		return sb;
	}

	protected String renderInput4Simply(Object value, Field field, PropertyConfig htmlInput, String type,
			List<String> submit, String contextPath, String name, Object fromRequest) throws IllegalAccessException
	{
		String onblurExt = "";
		if (this.onblur != null)
		{
			onblurExt = this.onblur;
		}
		String onchangeExt = "";
		if (this.onchange != null)
		{
			onchangeExt = this.onchange;
		}
		onblurExt = onblurExt.replaceAll("javascript:", "");
		onchangeExt = onchangeExt.replaceAll("javascript:", "");

		StringBuffer string = new StringBuffer();
		Object renderValue = fromRequest;
		if (renderValue == null)
		{
			if (value != null)
			{
				renderValue = field.get(value);
			}
		}
		Class<?> fieldType = field.getType();
		if (htmlInput.type().equals(HtmlInputType.ID) && ("hidden".equalsIgnoreCase(type)))
		{
			name = "old" + name;
		}
		String showValue = "";
		if (renderValue != null)
		{
			String pattern = htmlInput.format();
			if ((pattern != null) && pattern.length() > 0)
			{
				if (Date.class.isAssignableFrom(fieldType))
				{
					SimpleDateFormat sdf = new SimpleDateFormat(pattern);
					showValue = sdf.format((Date) renderValue);
				}
				else if (Integer.class.isAssignableFrom(fieldType))
				{
					DecimalFormat df = new DecimalFormat(pattern);
					showValue = df.format(renderValue);
				}
				else
				{
					MessageFormat mf = new MessageFormat(pattern);
					showValue = mf.format(renderValue);
				}
			}
			else
			{
				showValue = renderValue.toString();
			}
		}
		string.append("<input id=\"" + name + "\" type=\"" + type + "\" name=\"" + name + "\" value=\"" + showValue
				+ "\" ");
		if (!htmlInput.pattern().equals(com.hengpeng.common.web.annotation.HtmlInputPattern.NORMAL))
		{
			string.append("onchange=\"javascript: valid4" + this.command + "('" + htmlInput.label() + "','"
					+ htmlInput.pattern().getJspattern() + "',this.value,'valid4" + name + "', 'mask4" + name + "', '"
					+ !htmlInput.nullable() + "');" + onchangeExt + "\" ");
			string.append("onblur=\"javascript: valid4" + this.command + "('" + htmlInput.label() + "','"
					+ htmlInput.pattern().getJspattern() + "',this.value,'valid4" + name + "', 'mask4" + name + "', '"
					+ !htmlInput.nullable() + "');" + onblurExt + "\" ");
			string.append("/>");

			if (!"hidden".equalsIgnoreCase(type))
			{
				if (Date.class.isAssignableFrom(fieldType))
				{
					string.append("<img src=\"" + contextPath + "/images/calendar2.gif\" align=\"middle\" ");
					string.append("style=\"cursor: pointer\" id=\"img4"
							+ name
							+ "\" alt=\"时间\" onclick=\"init_datepicker('"
							+ name
							+ "','1');\" /><script language=\"javascript\" type=\"text/javascript\">Calendar.showDate(\""
							+ name + "\",\"img4" + name + "\");</script>");
				}
			}
		}
		else
		{
			string.append("/>");
		}
		if (!"hidden".equalsIgnoreCase(type))
		{
			string.append("&nbsp;");
			if (!htmlInput.nullable())
			{
				string.append("<span style=\"color:red;\">*</span>");
			}
			string.append("<span style=\"color:gray;font-style: italic;font-size: small;\">"
					+ htmlInput.pattern().getHint() + "</span>\r\n<div id=\"mask4" + name
					+ "\" style=\"display: none;\"></div>\r\n<div id=\"valid4" + name
					+ "\" style=\"display: none;color: red;font-size: small;\"></div>\r\n");
		}
		return string.toString();
	}

	protected String renderInput4TextArea(Object value, Field field, PropertyConfig htmlInput, String type,
			List<String> submit, String contextPath, String inputId, Object fromRequest) throws IllegalAccessException
	{
		String onblurExt = "";
		if (this.onblur != null)
		{
			onblurExt = this.onblur;
		}
		String onchangeExt = "";
		if (this.onchange != null)
		{
			onchangeExt = this.onchange;
		}
		onblurExt = onblurExt.replaceAll("javascript:", "");
		onchangeExt = onchangeExt.replaceAll("javascript:", "");

		StringBuffer string = new StringBuffer();
		Object renderValue = fromRequest;
		if (renderValue == null)
		{
			if (value != null)
			{
				renderValue = field.get(value);
			}
		}
		String showValue = "";
		Class<?> fieldType = field.getType();
		if (renderValue != null)
		{
			String pattern = htmlInput.format();
			if ((pattern != null) && pattern.length() > 0)
			{
				if (Date.class.isAssignableFrom(fieldType))
				{
					SimpleDateFormat sdf = new SimpleDateFormat(pattern);
					showValue = sdf.format((Date) renderValue);
				}
				else if (Integer.class.isAssignableFrom(fieldType))
				{
					DecimalFormat df = new DecimalFormat(pattern);
					showValue = df.format(renderValue);
				}
				else
				{
					MessageFormat mf = new MessageFormat(pattern);
					showValue = mf.format(renderValue);
				}
			}
			else
			{
				showValue = renderValue.toString();
			}
		}
		string.append("<textarea id=\"" + inputId + "\" name=\"" + inputId + "\" ");
		if (!htmlInput.pattern().equals(com.hengpeng.common.web.annotation.HtmlInputPattern.NORMAL))
		{
			string.append("onchange=\"javascript: valid4" + this.command + "('" + htmlInput.label() + "','"
					+ htmlInput.pattern().getJspattern() + "',this.value,'valid4" + inputId + "', 'mask4" + inputId
					+ "', '" + !htmlInput.nullable() + "');" + onchangeExt + "\" ");
			string.append("onblur=\"javascript: valid4" + this.command + "('" + htmlInput.label() + "','"
					+ htmlInput.pattern().getJspattern() + "',this.value,'valid4" + inputId + "', 'mask4" + inputId
					+ "', '" + !htmlInput.nullable() + "');" + onblurExt + "\" ");
			string.append(">");
			string.append(showValue);
			string.append("</textarea>");
			if (Date.class.isAssignableFrom(fieldType))
			{
				string.append("<img src=\"" + contextPath + "/images/calendar2.gif\" align=\"middle\" ");
				string.append("style=\"cursor: pointer\" id=\"img4" + inputId
						+ "\" alt=\"时间\" onclick=\"init_datepicker('" + inputId
						+ "','1');\" /><script language=\"javascript\" type=\"text/javascript\">Calendar.showDate(\""
						+ inputId + "\",\"img4" + inputId + "\");</script>");
			}
			if (!"hidden".equalsIgnoreCase(type))
			{
				string.append("&nbsp;");
			}
			if (!htmlInput.nullable())
			{
				string.append("<span style=\"color:red;\">*</span>");
			}
		}
		else
		{
			string.append(">");
			string.append(showValue);
			string.append("</textarea>");
			if (!"hidden".equalsIgnoreCase(type))
			{
				string.append("&nbsp;");
			}
			if (!htmlInput.nullable())
			{
				string.append("<span style=\"color:red;\">*</span>");
			}
		}
		if (!"hidden".equalsIgnoreCase(type))
		{
			string.append("<span style=\"color:gray;font-style: italic;font-size: small;\">"
					+ htmlInput.pattern().getHint() + "</span>\r\n<div id=\"mask4" + inputId
					+ "\" style=\"display: none;\"></div>\r\n<div id=\"valid4" + inputId
					+ "\" style=\"display: none;color: red;font-size: small;\"></div>\r\n");
		}
		return string.toString();
	}

	private String renderInputMultuple(String inputId, String type, Object selectValue, SingleObject so,
			PropertyConfig htmlInput) throws JspException
	{
		String onblurchange = "";
		if (this.onblur != null)
		{
			onblurchange = "onblur=\"" + this.onblur + "\" ";
		}
		if (this.onchange != null)
		{
			onblurchange = onblurchange + "onchange=\"" + this.onchange + "\" ";
		}
		StringBuffer string = new StringBuffer();
		if (isChecked(so, htmlInput, selectValue))
		{
			string.append("<input id=\"" + inputId + "\" type=\"" + type + "\" name=\"" + inputId + "\" value='"
					+ so.value + "' checked=\"checked\" " + onblurchange + "/>" + so.label + "\r\n");
		}
		else
		{
			string.append("<input id=\"" + inputId + "\" type=\"" + type + "\" name=\"" + inputId + "\" value='"
					+ so.value + "' " + onblurchange + "/>" + so.label + "\r\n");
		}
		return string.toString();
	}

	private String renderInputOption(Object value, SingleObject so, PropertyConfig htmlInput, Object selectValue)
			throws JspException
	{
		String htmlElement = "";
		if (isChecked(so, htmlInput, selectValue))
		{
			htmlElement = "<option value='" + so.value + "' selected=\"selected\">" + so.label + "</option>\r\n";
		}
		else
		{
			htmlElement = "<option value='" + so.value + "'>" + so.label + "</option>\r\n";
		}
		return htmlElement;
	}

	private void renderTitle(StringBuffer content, String contextPath)
	{
		content.append("<tr>\r\n<td width=\"12\" height=\"30\"><img src=\"" + contextPath
				+ "/layout/list/tab_left_top.gif\" width=\"12\" height=\"30\" /></td><td align='left'>");
		content.append("<img src=\"" + contextPath + "/layout/list/list.gif\" width=\"16\" height=\"16\" />");
		if (title != null)
		{
			content.append(title);
		}
		content.append("</td>\r\n");
		content.append("<td align='right'>\r\n&nbsp;\r\n</td><td width=\"16\"><img src=\"" + contextPath
				+ "/layout/list/tab_right_top.gif\" width=\"16\" height=\"30\" /></td>\r\n");
		content.append("</tr>\r\n");
	}

	public void setAction(String action)
	{
		this.action = action;
	}

	public void setColumn(int column)
	{
		this.column = column;
	}

	public void setCommand(String command)
	{
		this.command = command;
	}

	public void setExclude(String exclude)
	{
		this.exclude = exclude;
	}

	public void setMethod(String method)
	{
		this.method = method;
	}

	public void setNeedButton(boolean needButton)
	{
		this.needButton = needButton;
	}

	public void setNeedTitle(boolean needTitle)
	{
		this.needTitle = needTitle;
	}

	public void setOnblur(String onblur)
	{
		this.onblur = onblur;
	}

	public void setOnchange(String onchange)
	{
		this.onchange = onchange;
	}

	public void setOnSubmit(String onSubmit)
	{
		this.onSubmit = onSubmit;
	}

	public void setPropertys(List<CommandProperty> propertys)
	{
		this.propertys = propertys;
	}

	public void setReadonly(boolean readonly)
	{
		this.readonly = readonly;
	}

	public void setSubmitName(String submitName)
	{
		this.submitName = submitName;
	}

	public void setTarget(String target)
	{
		this.target = target;
	}

	public void setTitle(String title)
	{
		this.title = title;
	}

	private String wrapperElementValue(Object item, PropertyConfig htmlInput)
	{
		String valueProperty = htmlInput.valueProperty();

		BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(item);
		Object renderValue = new String("");
		if ((valueProperty != null) && (valueProperty.length() > 0))
		{
			renderValue = wrapper.getPropertyValue(valueProperty);
		}
		else if (item instanceof Enum<?>)
		{
			renderValue = ((Enum<?>) item).name();
		}
		else
		{
			renderValue = item;
		}
		return renderValue.toString();
	}

	private String wrapperElementShowValue(Object item, PropertyConfig htmlInput)
	{
		String valueProperty = htmlInput.valueProperty();
		if ((htmlInput.labelProperty() != null) && (htmlInput.labelProperty().length() > 0))
		{
			valueProperty = htmlInput.labelProperty();
		}
		BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(item);
		Object renderValue = new String("");
		if ((valueProperty != null) && (valueProperty.length() > 0))
		{
			renderValue = wrapper.getPropertyValue(valueProperty);
		}
		else if (item instanceof Enum<?>)
		{
			renderValue = ((Enum<?>) item).name();
		}
		else
		{
			renderValue = item;
		}
		return renderValue.toString();
	}

	private String wrapperEntryValue(Map.Entry<?, ?> entry, PropertyConfig htmlInput)
	{
		String valueProperty = htmlInput.valueProperty();
		Object mapKey = entry.getKey();
		BeanWrapper mapKeyWrapper = PropertyAccessorFactory.forBeanPropertyAccess(mapKey);
		Object renderValue = (((valueProperty != null) && (valueProperty.length() > 0)) ? mapKeyWrapper
				.getPropertyValue(valueProperty) : mapKey.toString());
		return renderValue.toString();
	}

	private SingleObject wrapperLabelValue(Object item, PropertyConfig htmlInput)
	{
		BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(item);
		Object renderValue;
		if ((htmlInput.valueProperty() != null) && (htmlInput.valueProperty().length() > 0))
		{
			renderValue = wrapper.getPropertyValue(htmlInput.valueProperty());
		}
		else if (item instanceof Enum<?>)
		{
			renderValue = ((Enum<?>) item).name();
		}
		else
		{
			renderValue = item;
		}
		Object renderLabel = (((htmlInput.labelProperty() != null) && (htmlInput.labelProperty().length() > 0)) ? wrapper
				.getPropertyValue(htmlInput.labelProperty()) : item);
		SingleObject so = new SingleObject();
		so.label = renderLabel.toString();
		so.value = renderValue.toString();
		return so;
	}

	private SingleObject wrapperMapLabelValue(Map.Entry<?, ?> entry, PropertyConfig htmlInput)
	{
		Object mapKey = entry.getKey();
		Object mapValue = entry.getValue();
		BeanWrapper mapKeyWrapper = PropertyAccessorFactory.forBeanPropertyAccess(mapKey);
		BeanWrapper mapValueWrapper = PropertyAccessorFactory.forBeanPropertyAccess(mapValue);
		Object renderValue = (((htmlInput.valueProperty() != null) && (htmlInput.valueProperty().length() > 0)) ? mapKeyWrapper
				.getPropertyValue(htmlInput.valueProperty()) : mapKey.toString());
		Object renderLabel = (((htmlInput.labelProperty() != null) && (htmlInput.labelProperty().length() > 0)) ? mapValueWrapper
				.getPropertyValue(htmlInput.labelProperty()) : mapValue.toString());
		SingleObject so = new SingleObject();
		so.label = renderLabel.toString();
		so.value = renderValue.toString();
		return so;
	}

	private StringBuffer wrapperMultipleValue(Field field, Object value, PropertyConfig htmlInput, Object requestItems)
			throws JspException, IllegalArgumentException, IllegalAccessException
	{
		StringBuffer sb = new StringBuffer();
		Object selected = "";
		if (value != null)
		{
			selected = field.get(value);
		}
		Object itemsObject = null;
		if (requestItems != null)
		{
			itemsObject = requestItems;
		}
		Class<?> boundType = field.getType();
		if (itemsObject == null && boundType != null && boundType.isEnum())
		{
			itemsObject = boundType.getEnumConstants();
		}
		if (boundType != null)
		{
			if (boundType.isArray())
			{
				Class<?> componentType = boundType.getComponentType();
				if (itemsObject == null && componentType != null && componentType.isEnum())
				{
					itemsObject = componentType.getEnumConstants();
				}
			}
			else if (Collection.class.isAssignableFrom(boundType))
			{
				Type genericType = field.getGenericType();
				Class<?> componentType = (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[0];
				if (itemsObject == null && componentType != null && componentType.isEnum())
				{
					itemsObject = componentType.getEnumConstants();
				}
			}
			else if (Map.class.isAssignableFrom(boundType))
			{
				Type genericType = field.getGenericType();
				Class<?> componentType = (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[1];
				if (itemsObject == null && componentType != null && componentType.isEnum())
				{
					itemsObject = componentType.getEnumConstants();
				}
			}
		}
		if (itemsObject != null)
		{
			if (itemsObject.getClass().isArray())
			{
				Object[] itemsArray = (Object[]) itemsObject;
				for (int i = 0; i < itemsArray.length; i++)
				{
					Object item = itemsArray[i];
					String so = wrapperElementValue(item, htmlInput);
					sb.append(renderElement(selected, so, htmlInput, item));
				}
			}
			else if (itemsObject instanceof Collection<?>)
			{
				final Collection<?> optionCollection = (Collection<?>) itemsObject;
				for (Iterator<?> it = optionCollection.iterator(); it.hasNext();)
				{
					Object item = it.next();
					String so = wrapperElementValue(item, htmlInput);
					sb.append(renderElement(selected, so, htmlInput, item));
				}
			}
			else if (itemsObject instanceof Map<?, ?>)
			{
				final Map<?, ?> optionMap = (Map<?, ?>) itemsObject;
				for (Iterator<?> it = optionMap.entrySet().iterator(); it.hasNext();)
				{
					Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next();
					String so = wrapperEntryValue(entry, htmlInput);
					sb.append(renderElement(selected, so, htmlInput, null));
				}
			}
			else
			{
				throw new IllegalArgumentException("Attribute 'items' must be a Collection, an Array or a Map");
			}
		}
		if (sb.length() > 0)
		{
			sb.deleteCharAt(sb.length() - 1);
		}
		return sb;
	}

	private String wrapperSimplyValue(Object value, Field field, PropertyConfig htmlInput, Object fromRequest)
			throws IllegalAccessException
	{
		Object renderValue = fromRequest;
		if (renderValue == null)
		{
			if (value != null)
			{
				renderValue = field.get(value);
			}
		}
		String showValue = "";
		if (renderValue != null)
		{
			String pattern = htmlInput.format();
			if ((pattern != null) && pattern.length() > 0)
			{
				Class<?> type = field.getType();
				if (Date.class.isAssignableFrom(type))
				{
					SimpleDateFormat sdf = new SimpleDateFormat(pattern);
					showValue = sdf.format((Date) renderValue);
				}
				else if (Integer.class.isAssignableFrom(type))
				{
					DecimalFormat df = new DecimalFormat(pattern);
					showValue = df.format(renderValue);
				}
				else
				{
					MessageFormat mf = new MessageFormat(pattern);
					showValue = mf.format(renderValue);
				}
			}
			else
			{
				showValue = wrapperElementShowValue(renderValue, htmlInput);
			}
		}
		return showValue;
	}
}